#import <stdio.h>
#import <libc.h>
#import <math.h>
#import <streams/streams.h>
#import <appkit/graphics.h>
#import <appkit/NXBitmapImageRep.h>
#import "NXBitmapImageRepControl.h"
#import "ImageControl.h"
#import "xbm.h"

@implementation XBM

unsigned char FlipBits(unsigned char inByte);

- init
{
	return self;
}

- free
{
	return self;
}

unsigned char FlipBits(unsigned char inByte)
{
	unsigned char		outByte = 0;
	int				inPos = 0x01, 
					outPos = 0x80;
					
	if (!inByte || (inByte == 0xFF)) return inByte;
	while (inPos) {
		if (inByte & inPos) {
			outByte |= outPos;
		}
		inPos <<= 1;
		outPos >>= 1;
	}
	return outByte;
}

- readFromStream: (NXStream *)stream from: sender;
{
	id				image;
	char				buffer1[100];
	char				buffer2[100];
	char				buffer3[100];
	char				buffer4[100];
	int				width = 0, height = 0;
	unsigned char		*ptr;
	unsigned char		*size;
	int				tmp;

#ifdef DEBUG
	fprintf(stderr, "Made it to read\n");
#endif

	do {
		NXScanf(stream, "%99[^\n]", buffer1); NXGetc(stream);
		if (!strncmp(buffer1, "#define", 7)) {
			sscanf(buffer1, "%s %s %s", buffer2, buffer3, buffer4);
			if (!strcmp(buffer3 + strlen(buffer3) - 5, "width")) {
				width = atoi(buffer4);
#ifdef DEBUG
				fprintf(stderr, "Width = %d\n", width);
#endif
			}
			else if (!strcmp(buffer3 + strlen(buffer3) - 6, "height")) {
				height = atoi(buffer4);
#ifdef DEBUG
				fprintf(stderr, "Height = %d\n", height);
#endif
			}
		}
	} while (strncmp(buffer1, "static", 6));
	
	image = [[NXBitmapImageRep alloc] 	initData: NULL
										pixelsWide: width
										pixelsHigh: height
										bitsPerSample: 1
										samplesPerPixel: 1
										hasAlpha: NO
										isPlanar: NO
										colorSpace: NX_OneIsBlackColorSpace
										bytesPerRow: 0
										bitsPerPixel: 0];
	ptr = [image data];
	size = ptr + (((width + 7) / 8) * height);
#ifdef DEBUG
	fprintf(stderr, "%p %p\n", ptr, size);
#endif
	NXGetc(stream);
	do {
		NXScanf(stream, "%[^,]", buffer1); NXGetc(stream);
		sscanf(buffer1, "%x", &tmp);
		*ptr++ = FlipBits(tmp);
	} while (ptr < size);

	return image;
}

- (BOOL)write: (id)image toStream: (NXStream *)stream from: sender;
{
	id				newImage;
	id				imageCon;
	unsigned char		*dataPtr;
	int				size, x;
	char				*nameBuffer;
	
	imageCon = [sender getImageControl: image];
#ifdef DEBUG
	fprintf(stderr, "1...");
#endif
	newImage = [imageCon ditherImage];
#ifdef DEBUG
	fprintf(stderr, "2...");
#endif
	[imageCon free];
#ifdef DEBUG
	fprintf(stderr, "3...");
#endif
	
	nameBuffer = [sender filename];
	NXPrintf(stream, "#define %s_width %d\n", nameBuffer, [newImage pixelsWide]);
	NXPrintf(stream, "#define %s_height %d\n", nameBuffer, [newImage pixelsHigh]);
	NXPrintf(stream, "static char %s_bits[] = {", nameBuffer);
	size = (([newImage pixelsWide] + 7) / 8)* [newImage pixelsHigh];
#ifdef DEBUG
	fprintf(stderr, "%d\n", size);
#endif
	for (x = 0, dataPtr = [newImage data]; x < size - 1; x++) {
		if (!(x % 12)) NXPrintf(stream, "\n   ");
		NXPrintf(stream, "0x%02X,", FlipBits(*dataPtr++ ^ 0xFF));
	}
	NXPrintf(stream, "0x%02X};\n", FlipBits(*dataPtr ^ 0xFF));
	
	[newImage free];
	
	return YES;
}

- readAllFromStream: (NXStream *)stream from: sender
{
	return nil;
}

- (BOOL)writeAll: (id)image toStream: (NXStream *)stream
{
	return NO;
}

- customSaveView: (int)width
{
	return nil;
}

- customOpenView: (int)width
{
	return nil;
}

- (char *)getFormatName
{
	return("X11 Portable Bitmap (XBM)");
}

 - (BOOL)setCustomParameter: (const char *)parameter withValue: (void *)ptr
{
	return NO;
}

 - (void *)getCustomParameter: (const char *)parameter
{
	return nil;
}

- (char *)copyrightNotice
{
	return "XBM Converter\nby Alex Raftis\nCopyright (c) 1991 Cal Poly State University\nEmail bugs to alex@data.ACS.CalPoly.EDU";
}
 
- (int)errorState
{
	return CONVERT_ERR_NONE;
}
 
 - (int)errorMessage
{
	return ERROR_NO_ERROR;
}

- (char *)errorStringMessage
{
	return NULL;
}
 
- (BOOL)needsWindowServer;
{
	return NO;
}

- (char *)protocolVersion
{
	return "1.0";
}

@end
